package tech.lq0.dreamaticvoyage.recipe;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import tech.lq0.dreamaticvoyage.Utils;
import tech.lq0.dreamaticvoyage.tools.RecipeTool;

import javax.annotation.Nullable;

public class FukamizuReactingRecipe implements Recipe<SimpleContainer> {

    public final Ingredient input;
    public final Ingredient up;
    public final Ingredient left;
    public final Ingredient down;
    public final Ingredient right;
    private final ItemStack result;
    public final int tick;
    private final ResourceLocation id;

    public FukamizuReactingRecipe(Ingredient input, Ingredient up, Ingredient down, Ingredient left, Ingredient right, ItemStack result, int tick, ResourceLocation id) {
        this.input = input;
        this.up = up;
        this.down = down;
        this.left = left;
        this.right = right;
        this.result = result;
        this.tick = tick;
        this.id = id;
    }

    @Override
    public boolean matches(SimpleContainer pContainer, Level pLevel) {
        if (pLevel.isClientSide()) {
            return false;
        }

        return input.test(pContainer.getItem(0)) && up.test(pContainer.getItem(1)) && left.test(pContainer.getItem(2)) &&
                down.test(pContainer.getItem(3)) && right.test(pContainer.getItem(4));
    }

    @Override
    public NonNullList<Ingredient> getIngredients() {
        return NonNullList.of(input, input, up, left, down, right);
    }

    @Override
    public ItemStack assemble(SimpleContainer pContainer, RegistryAccess pRegistryAccess) {
        return result.copy();
    }

    @Override
    public boolean canCraftInDimensions(int pWidth, int pHeight) {
        return true;
    }

    @Override
    public ItemStack getResultItem(@Nullable RegistryAccess pRegistryAccess) {
        return result.copy();
    }

    @Override
    public ResourceLocation getId() {
        return id;
    }

    @Override
    public boolean isSpecial() {
        return true;
    }

    @Override
    public RecipeSerializer<?> getSerializer() {
        return Serializer.INSTANCE;
    }

    @Override
    public RecipeType<?> getType() {
        return Type.INSTANCE;
    }

    public static class Type implements RecipeType<FukamizuReactingRecipe> {
        public static final Type INSTANCE = new Type();
        public static final String ID = "fukamizu_reacting";
    }

    public static class Serializer implements RecipeSerializer<FukamizuReactingRecipe> {

        public static final Serializer INSTANCE = new Serializer();
        public static final ResourceLocation ID = Utils.loc("fukamizu_reacting");

        @Override
        public FukamizuReactingRecipe fromJson(ResourceLocation pRecipeId, JsonObject pSerializedRecipe) {
            ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(pSerializedRecipe, "result"));
            JsonElement inputIngredient = GsonHelper.isArrayNode(pSerializedRecipe, "input") ?
                    GsonHelper.getAsJsonArray(pSerializedRecipe, "input") : GsonHelper.getAsJsonObject(pSerializedRecipe, "input");
            var input = Ingredient.fromJson(inputIngredient);
            var up = RecipeTool.getIngredientFromJson(pSerializedRecipe, "up");
            var down = RecipeTool.getIngredientFromJson(pSerializedRecipe, "down");
            var left = RecipeTool.getIngredientFromJson(pSerializedRecipe, "left");
            var right = RecipeTool.getIngredientFromJson(pSerializedRecipe, "right");
            int tick = GsonHelper.getAsInt(pSerializedRecipe, "tick", 200);

            return new FukamizuReactingRecipe(input, up, down, left, right, output, tick, pRecipeId);
        }

        @Override
        public @Nullable FukamizuReactingRecipe fromNetwork(ResourceLocation pRecipeId, FriendlyByteBuf pBuffer) {
            Ingredient input = Ingredient.fromNetwork(pBuffer);
            Ingredient up = Ingredient.fromNetwork(pBuffer);
            Ingredient down = Ingredient.fromNetwork(pBuffer);
            Ingredient left = Ingredient.fromNetwork(pBuffer);
            Ingredient right = Ingredient.fromNetwork(pBuffer);
            ItemStack output = pBuffer.readItem();
            int tick = pBuffer.readInt();

            return new FukamizuReactingRecipe(input, up, down, left, right, output, tick, pRecipeId);
        }

        @Override
        public void toNetwork(FriendlyByteBuf pBuffer, FukamizuReactingRecipe pRecipe) {
            pRecipe.input.toNetwork(pBuffer);
            pRecipe.up.toNetwork(pBuffer);
            pRecipe.down.toNetwork(pBuffer);
            pRecipe.left.toNetwork(pBuffer);
            pRecipe.right.toNetwork(pBuffer);
            pBuffer.writeItemStack(pRecipe.getResultItem(null), false);
            pBuffer.writeInt(pRecipe.tick);
        }
    }
}
